package com.moter.demo01.requirements;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.TimeUnit;

public class NIOServer {
    private ServerSocketChannel server = null;
    private Selector selector = null;
    private final int PORT = 9090;
    private final String PATH = "src\\main\\java\\com\\moter\\demo01\\requirements\\server.txt";

    public void initServer() {
        try {
            //开启服务器通道
            server = ServerSocketChannel.open();
            selector = Selector.open();
            //绑定并监听端口
            server.bind(new InetSocketAddress(PORT));
            //设置为非阻塞
            server.configureBlocking(false);
            //注册到selector
            server.register(selector, SelectionKey.OP_ACCEPT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //服务启动
    public void start() {
        try {
            //启动服务
            initServer();
            System.out.println("服务器已经启动");
            while (true) {
                while (selector.select(1) > 0) {
                    Set<SelectionKey> selectionKeys = selector.selectedKeys();//查看所有有反应的通道
                    Iterator<SelectionKey> iterator = selectionKeys.iterator();//获得迭代器
                    while (iterator.hasNext()) {//迭代
                        SelectionKey next = iterator.next();
                        iterator.remove();
                        if (next.isAcceptable()) {//如果是可连接的，
                            acceptHandler(next);
                        } else if (next.isReadable()) {//如果是信息
                            readHandler(next);
                        }
                    }
                }
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    //消息读取处理函数
    private void readHandler(SelectionKey next) {
        ByteBuffer byteBuffer = (ByteBuffer) next.attachment();
        SocketChannel client = (SocketChannel) next.channel();
        //读取文本
        read(byteBuffer, client);

        //如果连接断开就不写入
        if (client.isOpen()) {
            try {
                byteBuffer.clear();
                byteBuffer.put("正在处理中......".getBytes());
                byteBuffer.flip();
                client.write(byteBuffer);
                byteBuffer.clear();
                TimeUnit.SECONDS.sleep(2);//模拟处理信息延时
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
            //写入文本
            write(client);
        }
    }

    private void write(SocketChannel client) {

        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        File file = new File(PATH);
        try (
                FileInputStream fileInputStream = new FileInputStream(file);
                FileChannel channel = fileInputStream.getChannel();
        ) {
            while (true) {
                byteBuffer.clear();
                int read = channel.read(byteBuffer);
                if (read > 0) {
                    byteBuffer.flip();
                    client.write(byteBuffer);
                    byteBuffer.clear();
                } else {//读完
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        NIOServer server = new NIOServer();
        server.start();
    }

    //从客户端读文本
    public void read(ByteBuffer byteBuffer, SocketChannel client) {
        while (true) {
            try {
                byteBuffer.clear();
                int read = client.read(byteBuffer);
                if (read > 0) {//读到数据
                    //翻转，写模式变为读模式
                    byteBuffer.flip();
                    //创建字节数组读
                    byte[] data = new byte[byteBuffer.limit()];
                    byteBuffer.get(data);
                    System.out.print(new String(data));
                } else if (read == 0) {//数据读完或者空数据
                    break;
                } else {//断开连接
                    System.out.println("服务器断开连接");
                    client.close();
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //连接处理函数
    public void acceptHandler(SelectionKey next) {

        try {
            //获取客户端
            ServerSocketChannel sever = (ServerSocketChannel) next.channel();
            SocketChannel client = sever.accept();
            //设置为非阻塞
            client.configureBlocking(false);
            //新建一个ByteBuffer
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            //注册到selector
            client.register(selector, SelectionKey.OP_READ, byteBuffer);
            System.out.println("与客户端" + client.socket().getInetAddress() + "\t连接");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
